using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Needle.Core.Injection;

namespace Needle.Core.Activation
{

    /// <summary>
    /// Provides information for activating an instance.
    /// </summary>
    public interface IActivationInfo
    {
        /// <summary>
        /// The dependency id
        /// </summary>
        InstanceId Id { get; }
        /// <summary>
        /// The concrete type
        /// </summary>
        Type Type { get; }
        /// <summary>
        /// The constructor
        /// </summary>
        IInjectionSite Constructor { get; }
        /// <summary>
        /// Readonly list of method injection sites
        /// </summary>
        IList<IInjectionSite> Methods { get; }

    }

    /// <summary>
    /// Default implementation of IActivationInfo
    /// </summary>
    public class ActivationInfo : IActivationInfo
    {

        #region static fields

        private static readonly IInjectionSite[] EmptySites = new IInjectionSite[0];

        #endregion

        #region constructor

        /// <summary>
        /// Initializes a new instance
        /// </summary>
        public ActivationInfo(InstanceId id,
                             Type type,
                             IInjectionSite constructor,
                             IList<IInjectionSite> methods)
        {
            _Id = id;
            _Type = type;
            _Constructor = constructor;
            _Methods = AsReadOnly(methods);
        }

        #endregion

        #region IActivationInfo Members

        private InstanceId _Id;
        /// <summary>
        /// The id for this Activation info
        /// </summary>
        public InstanceId Id
        {
            get { return _Id; }
        }
        private Type _Type;
        /// <summary>
        /// The concrete type
        /// </summary>
        public Type Type
        {
            get { return _Type; }
        }

        private IInjectionSite _Constructor;
        /// <summary>
        /// The constructing method
        /// </summary>
        public IInjectionSite Constructor
        {
            get { return _Constructor; }
        }

        private IList<IInjectionSite> _Methods;
        /// <summary>
        /// The injected methods.
        /// </summary>
        public IList<IInjectionSite> Methods
        {
            get { return _Methods; }
        }

        #endregion

        #region private methods

        private IList<IInjectionSite> AsReadOnly(IList<IInjectionSite> sites)
        {
            if (sites != null && sites.Count > 0)
            {
                IInjectionSite[] arr = new IInjectionSite[sites.Count];
                sites.CopyTo(arr, 0);
                return new ReadOnlyCollection<IInjectionSite>(arr);
            }
            return new ReadOnlyCollection<IInjectionSite>(EmptySites);
        }

        #endregion

    }

}
